package org.lboot.flow.processor.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import cn.hutool.system.SystemUtil;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.lboot.flow.constant.FlowNodeTypeConst;
import org.lboot.flow.model.node.BaseModel;
import org.lboot.flow.model.node.CommandModel;
import org.lboot.flow.module.work.FlowWork;
import org.lboot.flow.module.work.params.FlowTaskParams;
import org.lboot.flow.processor.FlowNodeProcessor;
import org.springframework.stereotype.Service;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class CommandNodeProcessor implements FlowNodeProcessor {
    @Override
    public String getNodeType() {
        return FlowNodeTypeConst.COMMAND_NODE;
    }

    @SneakyThrows
    @Override
    public void process(FlowWork flowWork, FlowTaskParams taskParams) {
        FlowWork oldFlow = new FlowWork();
        BeanUtil.copyProperties(flowWork,oldFlow, CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        // 流程执行到下一步
        BaseModel currentNode = flowWork.getCurrentModel();
        // 获取节点类型
        CommandModel model = (CommandModel) currentNode;
        // 获取命令行节点
        String command = model.getCommand();
        // 是否记录日志
        Boolean enableLog = model.getEnableLog();
        // 不同系统环境，执行方式不一样
        String osName = SystemUtil.getOsInfo().getName().toLowerCase();

        ProcessBuilder processBuilder = new ProcessBuilder();
        // 如果是 windows 系统
        if (osName.contains("win")) {
            processBuilder.command("cmd.exe", "/c", command);
        } else{
            // Linux 系统
            processBuilder.command("bash", "-c", command);
        }
        // 启动进程
        Process process = processBuilder.start();
        // 获取脚本的标准输出
        String output = new BufferedReader(new InputStreamReader(process.getInputStream()))
                .lines()
                .collect(Collectors.joining("\n"));

        // 获取脚本的标准错误输出
        String errorOutput = new BufferedReader(new InputStreamReader(process.getErrorStream()))
                .lines()
                .collect(Collectors.joining("\n"));
        // 等待进程结束并获取退出值
        int exitCode = process.waitFor();
        // 为 0 代表执行成功
        if (exitCode == 0){
            // 获取处理脚本
            String runScript = model.getRunScript();
            if (Validator.isNotEmpty(runScript)){
                // 执行脚本不为空
                // 创建脚本引擎管理器
                ScriptEngineManager manager = new ScriptEngineManager();
                // 获取JavaScript脚本引擎
                ScriptEngine engine = manager.getEngineByName("JavaScript");
                // 传入参数
                engine.put("$",output);
                // 执行结果
                Object result = engine.eval(runScript);
            }else {

            }
            // 脚本为空
            if (enableLog){
                // 获取流程实例ID
                String flowWorkId = flowWork.getId();
                // 构建日志文件路径
                String logFilePath = "";
            }
        }else {
            // 执行失败

        }
    }

    @Override
    public void back(FlowWork flowWork, FlowTaskParams taskParams) {
        // 该节点不执行回退操作

    }

    @SneakyThrows
    public static void main(String[] args) {
        String command = "dir";
        ProcessBuilder processBuilder = new ProcessBuilder();
        processBuilder.command("cmd.exe", "/c", "java -version");
        // 启动进程
        Process process = processBuilder.start();
        // 获取脚本的标准输出
        String output = new BufferedReader(new InputStreamReader(process.getInputStream()))
                .lines()
                .collect(Collectors.joining("\n"));

        // 获取脚本的标准错误输出
        String errorOutput = new BufferedReader(new InputStreamReader(process.getErrorStream()))
                .lines()
                .collect(Collectors.joining("\n"));

        // 等待进程结束并获取退出值
        int exitCode = process.waitFor();
        System.out.println("Exit Code: " + exitCode);
        System.out.println("Standard Output: ");
        System.out.println(output);
        System.out.println("Error Output: ");
        System.out.println(errorOutput);
    }
}
